#ifndef GRAPH_H
#define GRAPH_H

#include <QWidget>
#include <QPoint>
#include <QColor>
#include <QVector>
#include <QLabel>
#include "model.h"
#include <QStack>
#include <QMouseEvent>
#include <QDebug>
#include <QPushButton>
#include <QLineEdit>
#include <QTextStream>
#define RADIUM 10
#define INF 40000
class Graph : public QWidget
{
    Q_OBJECT
public:
    struct Point    //点结构体
    {
        QPoint locate;//坐标
        QColor color;//颜色
        Point(){}//默认构造函数
        Point(QPoint locate,QColor color)
        {
            this->locate=locate;
            this->color=color;
        }
    };

    struct Arrow //箭头结构体
    {
        int start;//起点Id
        int end;//终点Id
        int length;//长度
        QColor color;//颜色
        Arrow(){}
        Arrow(int start,int end,int length,QColor color)
        {
            this->start=start;this->end=end;this->length=length;this->color=color;
        }
    };
    /**
     * @brief Graph 构造函数
     * @param parent 父组件
     * @param num 数量
     * @param way 方式
     */
    Graph(QWidget *parent = 0,int num = 2);
    /**
     * @brief ~Graph 析构函数
     */
    virtual ~Graph();
    Point ** getPoints(){return points;}
    /**
     * @brief renderPaint 渲染画必须实现的函数，测试时记得注释掉emmm
     */
    //virtual void renderPaint() = 0;//渲染画
protected:
    int num;//总点数
    int current;//当前点数
    int start;//起始点
    Point ** points;//点数组
    QLabel stateLabel;//提示语句
    int * distance;//源点到某点的距离
    int stage;//当前阶段
    QVector<Arrow> arrowList;//箭头数组
    /**
     * @brief putArrow 向数组中放置箭头
     */
    virtual void putArrow() = 0;
    /**
     * @brief saveModel 保存当前模型
     */
    virtual void saveModel() = 0;
    /**
     * @brief isUnDirected 查看增加一条边后是否会让图变成无向
     * @param start
     * @param end
     * @return
    virtual bool isUnDirected(int start,int end) = 0;
    */
    /**
     * @brief saveEdge  保存边信息
     * @param out 输出流
     */
    virtual void saveEdge(QTextStream & out) = 0;
    /**
     * @brief renderPaint 渲染图画
     */
    void renderPaint();
    /**
     * @brief getRandomMap 随机生成一张图
     */
    void getRandomMap();
    /**
     * @brief loadGraphFromFile 读取文件
     */
    void loadGraphFromFile();
    Model * model;//模型指针
    QStack<Model*> history;//保存历史模型便于撤销
public slots:
    void mouseReleaseEvent(QMouseEvent *event);//鼠标事件
    void saveGraphToFile();//保存当前图到文件中
private:
    /**
     * @brief paintEvent 绘画事件
     */
    void paintEvent(QPaintEvent *);
    /**
     * @brief canBePut 检查对应坐标能否放置点
     * @param x 横坐标
     * @param y 纵坐标
     * @return 是否可以
     */
    bool canBePut(int x,int y);
    /**
     * @brief isExist 查看某个点是否存在，若存在，返回序号，否则-1
     * @param x 横坐标
     * @param y 纵坐标
     * @return 返回-1或序号
     */
    int isExist(const int &x, const int &y);
    /**
     * @brief leftEvent 实现鼠标左键事件
     * @param event
     * @return 事件是否对模型有影响
     */
    bool leftEvent(QMouseEvent * event);
    /**
     * @brief LGraph::rightEvent 用于撤销操作，利用栈结构来实现数据模型的存储
     */
    void rightEvent();
    /**
     * @brief LGraph::midEvent 用于结束当前阶段与进入下一阶段
     */
    bool midEvent();


    QLabel fileName;
    QPushButton * saveFileButton;//保存数据按钮
    QLineEdit * fileNameInput;//文件名输入框
};

#endif // GRAPH_H
